package com.facedemo.face;

import android.graphics.Bitmap;
import android.graphics.Rect;
import android.hardware.Camera;
import android.view.SurfaceView;
import android.widget.RelativeLayout;

import com.facedemo.MyApplication;
import com.facedemo.bean.DCamera;
import com.facedemo.face.callback.FaceRegisterCallback;
import com.facedemo.utils.ConvertDataInfo;
import com.facedemo.utils.DisplayUtil;
import com.facedemo.utils.ImageUtils;
import com.facedemo.utils.LogUtils;
import com.facedemo.view.CameraSurface;
import com.facedemo.view.FaceMarkSurface;

import net.facelib.mtfsdk.FaceApiMtfV2Android;
import net.facelib.mtfsdk.NativeFaceInfo;
import net.gdface.sdk.CodeInfo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class FaceRegisterUtil implements Camera.PreviewCallback,CameraSurface.SurfaceViewCallback {
    private Camera mCamera;
    private CameraSurface cameraSurface;
    private FaceMarkSurface faceRectView;
    private DCamera cameraConfig;

    private FaceRegisterCallback faceCallback;
    private ConvertDataInfo convertDataInfo;

    public FaceRegisterUtil(CameraSurface cameraSurface,FaceMarkSurface faceMarkSurface) {
        init(cameraSurface,faceMarkSurface);
    }

    private void init(CameraSurface cameraSurface,FaceMarkSurface faceMarkSurface) {
        cameraConfig = MyApplication.dCamera;
        convertDataInfo = new ConvertDataInfo(cameraConfig.cameraDataRotate,
                cameraConfig.cameraWidth,
                cameraConfig.cameraHeight);

        setCameraSurface(cameraSurface);
        setFaceMarkSurfaceView(faceMarkSurface);
    }

    public void setFaceCallback(FaceRegisterCallback faceCallback) {
        this.faceCallback = faceCallback;
    }

    private void setCameraSurface(CameraSurface cameraSurface) {
        this.cameraSurface = cameraSurface;
        cameraSurface.setSurfaceCallback(this);

        this.cameraSurface.post(new Runnable() {
            @Override
            public void run() {
                updateSurfaceSize(FaceRegisterUtil.this.cameraSurface);
            }
        });
    }

    private void setFaceMarkSurfaceView (FaceMarkSurface faceMarkSurface) {
        this.faceRectView = faceMarkSurface;
        this.faceRectView.post(new Runnable() {
            @Override
            public void run() {
                updateSurfaceSize(FaceRegisterUtil.this.faceRectView);
            }
        });
    }

    private void updateSurfaceSize(SurfaceView surfaceView) {
        if(surfaceView==null) return;

        int cameraW = cameraConfig.cameraWidth;
        int cameraH = cameraConfig.cameraHeight;
        if(cameraConfig.displayOrientation==90 || cameraConfig.displayOrientation==270) {
            cameraW = cameraConfig.cameraHeight;
            cameraH = cameraConfig.cameraWidth;
        }

        float cameraScale = (float)cameraW/(float)cameraH;
        RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)surfaceView.getLayoutParams();
        lp.width = DisplayUtil.getWindowWidth();
        lp.height = (int)(lp.width  / cameraScale);
        surfaceView.setLayoutParams(lp);
    }

    @Override
    public void surfaceCreated() {
        mCamera = Camera.open(cameraConfig.cameraId);
        Camera.Parameters parameters = mCamera.getParameters();

        boolean isPreviewSizeRight = false;
        List<Camera.Size> list = parameters.getSupportedPreviewSizes();
        for(int i=0;i<list.size();i++) {
            Camera.Size size = list.get(i);
            LogUtils.printD("camear parameters w:"+size.width+" h:"+size.height);
            if(size.width==cameraConfig.cameraWidth && size.height==cameraConfig.cameraHeight) {
                isPreviewSizeRight = true;
            }
        }

        if(isPreviewSizeRight) {
            parameters.setPreviewSize(cameraConfig.cameraWidth, cameraConfig.cameraHeight);
            mCamera.setParameters(parameters);

            try {
                mCamera.setDisplayOrientation(cameraConfig.displayOrientation);
                mCamera.setPreviewCallback(this);
                mCamera.setPreviewDisplay(cameraSurface.getCameraSufaceHolder());
                mCamera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
                mCamera = null;
            }
        } else {
            LogUtils.printE("请正确设置摄像头分辨率");
            if (mCamera!=null) {
                mCamera.setPreviewCallback(null);
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            }
        }
    }

    @Override
    public void surfaceDestroyed() {
        if (mCamera!=null) {
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    private boolean toGetFace = false;
    //获取一张人脸
    public void startGetFace() {
        toGetFace = true;
    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        if(!toGetFace || !FaceLicenseManger.isVaild) return;

        //摄像头图像数据转换
        convertDataInfo.convert(data,true);
        //人脸检测
        NativeFaceInfo faceDetectResult = FaceApiMtfV2Android.getInstance().nativeDetectMaxFace(convertDataInfo.getDataBGR(),convertDataInfo.getWidthBGR(),convertDataInfo.getHeightBGR(),1);

        List<CodeInfo> faceInfos = new ArrayList<>();;//检测结果
        FaceApiMtfV2Android.getInstance().nativeDetectFace(convertDataInfo.getDataBGR(),convertDataInfo.getWidthBGR(),convertDataInfo.getHeightBGR(),faceInfos,1);//用多人脸检测注册的人脸数

        int maxfacePos = -1; double minDis = convertDataInfo.getWidthBGR();
        for (int i = 0; i < faceInfos.size();i++)//选择靠近图像最中间的人脸
        {
            double picCenterx = convertDataInfo.getWidthBGR()/2;
            double picCentery = convertDataInfo.getHeightBGR()/2;

            double faceCenterx =  faceInfos.get(i).getPos().getLeft() + faceInfos.get(i).getPos().getWidth()/2;
            double faceCentery = faceInfos.get(i).getPos().getTop() + faceInfos.get(i).getPos().getHeight()/2;
           double dis = Math.sqrt((picCenterx - faceCenterx)* (picCenterx - faceCenterx)+(picCentery - faceCentery)* (picCentery - faceCentery));
           if (dis < minDis)
           {
               maxfacePos = i;
               minDis = dis;
           }
        }
        if(maxfacePos!=-1) { //如果最中间的人脸存在，则进行下一步的注册
           /* Rect rect = new Rect(faceDetectResult.getPos().getLeft(),
                    faceDetectResult.getPos().getTop(),
                    faceDetectResult.getPos().getLeft() + faceDetectResult.getPos().getWidth(),
                    faceDetectResult.getPos().getTop() + faceDetectResult.getPos().getHeight());*/
            Rect rect = new Rect(faceInfos.get(maxfacePos).getPos().getLeft(),faceInfos.get(maxfacePos).getPos().getTop(),
                    faceInfos.get(maxfacePos).getPos().getLeft() + faceInfos.get(maxfacePos).getPos().getWidth(),
                    faceInfos.get(maxfacePos).getPos().getTop() + faceInfos.get(maxfacePos).getPos().getHeight());

            //绘制人脸框
            if(faceRectView!=null) {
                faceRectView.drawInfo(rect,convertDataInfo.getWidthBGR(),convertDataInfo.getHeightBGR());
            }

            //提取人脸特征
            byte[] feaA = FaceApiMtfV2Android.getInstance().nativeGetFaceFeature(convertDataInfo.getDataBGR(),
                    convertDataInfo.getWidthBGR(),convertDataInfo.getHeightBGR(),faceDetectResult);
            if(feaA!=null) {
                //完成
                toGetFace = false;
                if(faceRectView!=null) {
                    faceRectView.clearDrawInfo();
                }

                if(faceCallback!=null) {

                    //图片旋转
                    Bitmap bitmapRGB = convertDataInfo.getBitmapRGB();
                    int rotate = cameraConfig.cameraDataRotate;
                    if(rotate == 90 || rotate == 270 || rotate == 180){
                        bitmapRGB = ImageUtils.rotate(bitmapRGB,rotate,0,0);
                    }
                    faceCallback.success(bitmapRGB,feaA);
                }
            }
        } else {
            if(faceRectView!=null) {
                faceRectView.clearDrawInfo();
            }
        }
    }
}